using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;
using System.Data;
using System.Globalization;

namespace it.mintlab.desktopnet.mintar
{
    public class ModelPanel<T> : TableLayoutPanel where T : new()
    {
        public ModelPanel(Size size, Point location): this()
        {
            this.Size = size;
            this.Location = location;
        }

        public ModelPanel() 
        {
            Type TClass = typeof(T);
            PropertyInfo[] properties = TClass.GetProperties();
            this.ColumnCount = 2;
            this.RowCount = properties.Length;
            foreach (PropertyInfo pi in properties)
            {
                //if panel attribute is present
                ModelPanelAttr[] panelAttrs = (ModelPanelAttr[])pi.GetCustomAttributes(typeof(ModelPanelAttr), true);
                if (panelAttrs.Length >= 1)
                {

                    //LABEL
                    Label lb = new Label();
                    lb.Width = 100;
                    lb.TextAlign = ContentAlignment.MiddleLeft;
                    lb.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                    lb.Name = "lb" + pi.Name;
                    lb.Text = panelAttrs[0].label;
                    this.Controls.Add(lb);

                    //BOX
                    Control control;
                    //if drop down list for properties
                    if (!panelAttrs[0].listingTable.Equals(""))
                    {
                        ComboBox cb = new ComboBox();
                        MethodInfo mi = TClass.GetMethod("getDataList", new Type[] { typeof(String) });
                        cb.DataSource = (DataTable)mi.Invoke(null, new Object[] { panelAttrs[0].listingTable });
                        cb.DisplayMember = "value";
                        cb.ValueMember = "id";
                        cb.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                        control = cb;
                    }
                    // if text box forcing for properties
                    else if (panelAttrs[0].forceTextBox)
                    {
                        control = new TextBox();
                    }
                    else
                    {
                        if (pi.PropertyType.Equals(typeof(bool)))
                        {
                            control = new CheckBox();
                        }
                        else if (pi.PropertyType.Equals(typeof(DateTime)))
                        {
                            DateTimePicker dtTmPc = new DateTimePicker();
                            dtTmPc.Format = DateTimePickerFormat.Short;
                            control = dtTmPc;
                        }
                        else
                        {
                            control = new TextBox();
                        }

                    }
                    control.Width = 100;
                    control.Name = "bx" + pi.Name;
                    this.Controls.Add(control);

                }
            }
        }

        public void bindModel(T modelObj)
        {
            Type TClass = typeof(T);
            PropertyInfo[] properties = TClass.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                //if panel attribute is present
                ModelPanelAttr[] panelAttrs = (ModelPanelAttr[])pi.GetCustomAttributes(typeof(ModelPanelAttr), true);
                if (panelAttrs.Length >= 1)
                {
                    foreach (Control c in this.Controls)
                    {
                        if (c.Name.Equals("bx" + pi.Name))
                        {
                            //if drop down list
                            if (!panelAttrs[0].listingTable.Equals(""))
                            {
                                ((ComboBox)c).SelectedValue = (int)pi.GetValue(modelObj, null);
                            }
                            // if text box forcing for properties
                            else if (panelAttrs[0].forceTextBox)
                            {
                                if (pi.PropertyType.Equals(typeof(bool)))
                                {
                                    ((TextBox)c).Text = ((bool)pi.GetValue(modelObj, null)).ToString();
                                }
                                else if (pi.PropertyType.Equals(typeof(DateTime)))
                                {
                                    ((TextBox)c).Text = ((DateTime)pi.GetValue(modelObj, null)).ToString(panelAttrs[0].dateFormat);
                                }
                            }
                            else
                            {
                                if (pi.PropertyType.Equals(typeof(bool)))
                                {
                                    ((CheckBox)c).Checked = (bool)pi.GetValue(modelObj, null);
                                }
                                else if (pi.PropertyType.Equals(typeof(DateTime)))
                                {
                                    ((DateTimePicker)c).Value = (DateTime)pi.GetValue(modelObj, null);
                                }
                                else
                                {
                                    ((TextBox)c).Text = pi.GetValue(modelObj, null).ToString();
                                }
                            }
                        }
                    }
                }
            }
        }

        public T getModel()
        {
            T modelObj = new T();
            //ConstructorInfo ci = TClass.GetConstructor(new Type[] { });
            //T modelObj = (T)ci.Invoke(new object[]{});
            Type TClass = typeof(T);
            PropertyInfo[] properties = TClass.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                //if panel attribute is present
                ModelPanelAttr[] panelAttrs = (ModelPanelAttr[])pi.GetCustomAttributes(typeof(ModelPanelAttr), true);
                if (panelAttrs.Length >= 1)
                {

                    foreach (Control c in this.Controls)
                    {
                        if (c.Name.Equals("bx" + pi.Name))
                        {
                            //if drop down list
                            if (!panelAttrs[0].listingTable.Equals(""))
                            {
                                int value = (int)((ComboBox)c).SelectedValue;
                                if (value == -1)
                                {
                                    MessageBox.Show("Campo '" + panelAttrs[0].label + "' non definito");
                                    return default(T);
                                }
                                else
                                    pi.SetValue(modelObj, value, null);
                            }
                            // if text box forcing for properties
                            else if (panelAttrs[0].forceTextBox)
                            {
                                if (pi.PropertyType.Equals(typeof(bool)))
                                {
                                    if (c.Text.Equals("True") ||
                                        c.Text.Equals("true") ||
                                        c.Text.Equals("Vero") ||
                                        c.Text.Equals("vero") ||
                                        c.Text.Equals("1"))
                                    {
                                        pi.SetValue(modelObj, true, null);
                                    }
                                    else 
                                    {
                                        pi.SetValue(modelObj, false, null);
                                    }
                                }
                                else if (pi.PropertyType.Equals(typeof(DateTime)))
                                {
                                    try
                                    {
                                        DateTime value = DateTime.ParseExact(c.Text, panelAttrs[0].dateFormat,
                                            CultureInfo.InvariantCulture);

                                        pi.SetValue(modelObj, value, null);
                                    }
                                    catch
                                    {
                                        MessageBox.Show("Campo '" + panelAttrs[0].label + "' non data");
                                        return default(T);
                                    }
                                }
                            }
                            else
                            {
                                if (pi.PropertyType.Equals(typeof(bool)))
                                {
                                    pi.SetValue(modelObj, ((CheckBox)c).Checked, null);
                                }
                                else if (pi.PropertyType.Equals(typeof(DateTime)))
                                {
                                    DateTime date = ((DateTimePicker)c).Value;
                                    date = date.Subtract(new TimeSpan(date.Hour,date.Minute, date.Second));
                                    pi.SetValue(modelObj, date, null);
                                }
                                else if (pi.PropertyType.Equals(typeof(int)))
                                {
                                    try
                                    {
                                        int value = int.Parse(c.Text);
                                        pi.SetValue(modelObj, value, null);
                                    }
                                    catch
                                    {
                                        MessageBox.Show("Campo '" + panelAttrs[0].label + "' non intero");
                                        return default(T);
                                    }
                                }
                                else if (pi.PropertyType.Equals(typeof(decimal)))
                                {
                                    try
                                    {
                                        decimal value = decimal.Parse(c.Text);
                                        pi.SetValue(modelObj, value, null);
                                    }
                                    catch
                                    {
                                        MessageBox.Show("Campo '" + panelAttrs[0].label + "' non decimale");
                                        return default(T);
                                    }
                                }
                                else
                                {
                                    pi.SetValue(modelObj, c.Text, null);
                                }
                            }
                        }
                    }
                }
            }
            return modelObj;
        }

        public void clear()
        {
            Type TClass = typeof(T);
            PropertyInfo[] properties = TClass.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                //if panel attribute is present
                ModelPanelAttr[] panelAttrs = (ModelPanelAttr[])pi.GetCustomAttributes(typeof(ModelPanelAttr), true);
                if (panelAttrs.Length >= 1)
                {

                    foreach (Control c in this.Controls)
                    {
                        if (c.Name.Equals("bx" + pi.Name))
                        {
                            //if drop down list
                            if (!panelAttrs[0].listingTable.Equals(""))
                            {
                                ((ComboBox)c).SelectedIndex = 0;
                            }
                            // if text box forcing for properties
                            else if (panelAttrs[0].forceTextBox)
                            {
                                ((TextBox)c).Text = "";
                            }
                            else
                            {
                                if (pi.PropertyType.Equals(typeof(bool)))
                                {
                                    ((CheckBox)c).CheckState = CheckState.Indeterminate;
                                }
                                else if (pi.PropertyType.Equals(typeof(DateTime)))
                                {
                                    ((DateTimePicker)c).Value = DateTime.Now;
                                }
                                else
                                {
                                    ((TextBox)c).Text = "";
                                }
                            }
                        }
                    }
                }
            }
        }

        public void enable(bool enabled)
        {
            Type TClass = typeof(T);
            PropertyInfo[] properties = TClass.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                //if panel attribute is present
                ModelPanelAttr[] panelAttrs = (ModelPanelAttr[])pi.GetCustomAttributes(typeof(ModelPanelAttr), true);
                if (panelAttrs.Length >= 1)
                {

                    foreach (Control c in this.Controls)
                    {
                        if (c.Name.Equals("bx" + pi.Name))
                        {
                            if (c is TextBox)
                            {
                                if (enabled)
                                    ((TextBox)c).ReadOnly = false;
                                else
                                    ((TextBox)c).ReadOnly = true;
                            }
                            else
                            {
                                if (enabled)
                                    c.Enabled = true;
                                else
                                    c.Enabled = false;
                            }
                        }
                    }

                }
            }
        }
    }
}
